package de.slothsoft.commons.swing;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;

import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.TransferHandler;

public class JDraggableLabel extends JLabel implements Transferable,
		DragGestureListener {

	// TODO: implement setDragEnabled(boolean) and the getter

	private static final long serialVersionUID = 1L;
	private static final DataFlavor[] flavors = new DataFlavor[] { DataFlavor.stringFlavor };

	private LabelTransferHandler transferHandler;

	public JDraggableLabel() {
		initialize();
	}

	public JDraggableLabel(Icon icon, int horizontalAlignment) {
		super(icon, horizontalAlignment);
		initialize();
	}

	public JDraggableLabel(Icon icon) {
		super(icon);
		initialize();
	}

	public JDraggableLabel(String text, Icon icon, int horizontalAlignment) {
		super(text, icon, horizontalAlignment);
		initialize();
	}

	public JDraggableLabel(String text, int horizontalAlignment) {
		super(text, horizontalAlignment);
		initialize();
	}

	public JDraggableLabel(String text) {
		super(text);
		initialize();
	}

	/*
	 * Create the drag source
	 */

	private void initialize() {
		// Use the default DragSource
		DragSource dragSource = DragSource.getDefaultDragSource();

		// Create a DragGestureRecognizer and
		// register as the listener
		dragSource.createDefaultDragGestureRecognizer(this,
				DnDConstants.ACTION_COPY_OR_MOVE, this);
	}

	@Override
	public void setTransferHandler(TransferHandler newHandler) {
		setTransferHandler((LabelTransferHandler) newHandler);
	}

	public void setTransferHandler(LabelTransferHandler newHandler) {
		this.transferHandler = newHandler;
	}

	@Override
	public LabelTransferHandler getTransferHandler() {
		return this.transferHandler;
	}

	/*
	 * Implementation of the DragSourceListener interface
	 */

	@Override
	public void dragGestureRecognized(DragGestureEvent dge) {
		Transferable transferable = this;
		if (this.transferHandler != null) {
			transferable = this.transferHandler.createTransferable(this);
		}
		dge.startDrag(null, transferable);
	}

	/*
	 * Implementation of the Transferable interface
	 */

	@Override
	public DataFlavor[] getTransferDataFlavors() {
		return flavors;
	}

	@Override
	public boolean isDataFlavorSupported(DataFlavor fl) {
		for (int i = 0; i < flavors.length; i++) {
			if (fl.equals(flavors[i])) {
				return true;
			}
		}

		return false;
	}

	@Override
	public Object getTransferData(DataFlavor fl) {
		if (!isDataFlavorSupported(fl)) {
			return null;
		}

		if (fl.equals(DataFlavor.stringFlavor)) {
			// String - return the text as a String
			return getText();
		}

		// else - return an String, too
		return getText();
	}

	/*
	 * 
	 */

	public static abstract class LabelTransferHandler extends TransferHandler {

		private static final long serialVersionUID = 1L;

		@Override
		public Transferable createTransferable(JComponent c) {
			return super.createTransferable(c);
		}
	}

}
